home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre1.z / postgre1 / test / postfs.usr.bin / ls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  14.9 KB  |  722 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. char copyright[] =
  9. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  10.  All rights reserved.\n";
  11. #endif not lint
  12.  
  13. #ifndef lint
  14. static    char sccsid[] = "@(#)ls.c 1.1 90/03/23 SMI"; /* from UCB 5.6 5/12/86 */
  15. #endif not lint
  16.  
  17. /*
  18.  * ls
  19.  *
  20.  * 4.2bsd version for symbolic links, variable length
  21.  * directory entries, block size in the inode, etc.
  22.  */
  23. #include <sys/param.h>
  24. /*#include <sys/stat.h>*/
  25. #include <sys/dir.h>
  26. #include <stdio.h>
  27. #include <sgtty.h>
  28. #include <errno.h>
  29. #include "tmp/libpq-fs.h"
  30.  
  31. extern int p_errno;
  32. extern char *PQexec();
  33. extern char *getenv();
  34.  
  35. #include <ctype.h>
  36. #include <locale.h>
  37.  
  38. #define    kbytes(size)    (((size) + 1023) / 1024)
  39.  
  40. struct afile {
  41.     char    ftype;        /* file type, e.g. 'd', 'c', 'f' */
  42.     ino_t    fnum;        /* inode number of file */
  43.     short    fflags;        /* mode&~S_IFMT, perhaps ISARG */
  44.     short    fnl;        /* number of links */
  45.     uid_t    fuid;        /* owner id */
  46.     gid_t    fgid;        /* group id */
  47.     long    fsize;        /* file size */
  48.     long    fblks;        /* number of blocks used */
  49.     time_t    fmtime;        /* time (modify or access or create) */
  50.     char    *fname;        /* file name */
  51.     char    *flinkto;    /* symbolic link value */
  52. };
  53.  
  54. #define    ISARG    0x8000        /* extra ``mode'' */
  55.  
  56. struct subdirs {
  57.     char    *sd_name;
  58.     struct    subdirs *sd_next;
  59. } *subdirs;
  60.  
  61. int    aflg, dflg, gflg, lflg, sflg, tflg, uflg, iflg, fflg, cflg, rflg = 1;
  62. int    qflg, Aflg, Cflg, Fflg, Lflg, Rflg;
  63.  
  64. int    usetabs;
  65.  
  66. time_t    now, sixmonthsago, onehourfromnow;
  67.  
  68. char    *dotp = ".";
  69.  
  70. struct    winsize win;
  71. int    twidth;
  72.  
  73. struct    afile *gstat();
  74. int    fcmp();
  75. char    *cat(), *savestr();
  76. char    *fmtentry();
  77. static char    *getname(), *getgroup();
  78.  
  79. char    *ctime();
  80. char    *malloc(), *calloc(), *realloc();
  81. char    *sprintf(), *strcpy(), *strcat();
  82.  
  83. #define p_exit(x) \
  84.     {\
  85.         PQfinish();\
  86.         exit(x);\
  87.     }
  88.  
  89. #define lstat p_stat
  90.  
  91. main(argc, argv)
  92.     int argc;
  93.     char *argv[];
  94. {
  95.     int i;
  96.     struct afile *fp0, *fplast;
  97.     register struct afile *fp;
  98.     struct sgttyb sgbuf;
  99.     char *dbname;
  100.  
  101.     if ((dbname = getenv("DATABASE")) == (char *) NULL) {
  102.         fprintf(stderr, "no database specified in env var DATABASE\n");
  103.         fflush(stderr);
  104.         exit (1);
  105.     }
  106.  
  107.     PQsetdb(dbname);
  108.  
  109.     argc--, argv++;
  110.     if (getuid() == 0)
  111.         Aflg++;
  112.     (void) time(&now);
  113.     sixmonthsago = now - 6L*30L*24L*60L*60L;
  114.     onehourfromnow = now + 60L*60L;
  115.     now += 60;
  116.     twidth = 80;
  117.     if (isatty(1)) {
  118.         qflg = Cflg = 1;
  119.         (void) gtty(1, &sgbuf);
  120.         if (ioctl(1, TIOCGWINSZ, &win) != -1)
  121.             twidth = (win.ws_col == 0 ? 80 : win.ws_col);
  122.         if ((sgbuf.sg_flags & XTABS) != XTABS)
  123.             usetabs = 1;
  124.     } else
  125.         usetabs = 1;
  126.  
  127.     setlocale(LC_ALL, "");            /* get local environment */
  128.  
  129.     while (argc > 0 && **argv == '-') {
  130.         (*argv)++;
  131.         while (**argv) switch (*(*argv)++) {
  132.  
  133.         case 'C':
  134.             Cflg = 1; break;
  135.         case 'q':
  136.             qflg = 1; break;
  137.         case '1':
  138.             Cflg = 0; break;
  139.         case 'a':
  140.             aflg++; break;
  141.         case 'A':
  142.             Aflg++; break;
  143.         case 'c':
  144.             cflg++; break;
  145.         case 's':
  146.             sflg++; break;
  147.         case 'd':
  148.             dflg++; break;
  149.         case 'g':
  150.             gflg++; break;
  151.         case 'l':
  152.             lflg++; break;
  153.         case 'r':
  154.             rflg = -1; break;
  155.         case 't':
  156.             tflg++; break;
  157.         case 'u':
  158.             uflg++; break;
  159.         case 'i':
  160.             iflg++; break;
  161.         case 'f':
  162.             fflg++; break;
  163.         case 'L':
  164.             Lflg++; break;
  165.         case 'F':
  166.             Fflg++; break;
  167.         case 'R':
  168.             Rflg++; break;
  169.         }
  170.         argc--, argv++;
  171.     }
  172.     if (fflg) {
  173.         aflg++; lflg = 0; sflg = 0; tflg = 0;
  174.     }
  175.     if (lflg)
  176.         Cflg = 0;
  177.     if (argc == 0) {
  178.         argc++;
  179.         argv = &dotp;
  180.     }
  181.     fp = (struct afile *)calloc(argc, sizeof (struct afile));
  182.     if (fp == 0) {
  183.         fprintf(stderr, "ls: out of memory\n");
  184.         p_exit(1);
  185.     }
  186.     fp0 = fp;
  187.     for (i = 0; i < argc; i++) {
  188.         if (gstat(fp, *argv, 1, (int *)0)) {
  189.             fp->fname = *argv;
  190.             fp->fflags |= ISARG;
  191.             fp++;
  192.         }
  193.         argv++;
  194.     }
  195.     fplast = fp;
  196.     qsort(fp0, fplast - fp0, sizeof (struct afile), fcmp);
  197.     if (dflg) {
  198.         formatf(fp0, fplast);
  199.         p_exit(0);
  200.     }
  201.     if (fflg)
  202.         fp = fp0;
  203.     else {
  204.         for (fp = fp0; fp < fplast && fp->ftype != 'd'; fp++)
  205.             continue;
  206.         formatf(fp0, fp);
  207.     }
  208.     if (fp < fplast) {
  209.         if (fp > fp0)
  210.             printf("\n");
  211.         for (;;) {
  212.             formatd(fp->fname, argc > 1);
  213.             while (subdirs) {
  214.                 struct subdirs *t;
  215.  
  216.                 t = subdirs; subdirs = t->sd_next;
  217.                 printf("\n");
  218.                 formatd(t->sd_name, 1);
  219.                 cfree(t->sd_name);
  220.                 cfree((char *)t);
  221.             }
  222.             if (++fp == fplast)
  223.                 break;
  224.             printf("\n");
  225.         }
  226.     }
  227.     p_exit(0);
  228.     /* NOTREACHED */
  229. }
  230.  
  231. formatd(name, title)
  232.     char *name;
  233.     int title;
  234. {
  235.     register struct afile *fp;
  236.     register struct subdirs *dp;
  237.     struct afile *dfp0, *dfplast;
  238.     int nkb;
  239.  
  240.     nkb = getdir(name, &dfp0, &dfplast);
  241.     if (dfp0 == 0)
  242.         return;
  243.     if (fflg == 0)
  244.         qsort(dfp0, dfplast - dfp0, sizeof (struct afile), fcmp);
  245.     if (title)
  246.         printf("%s:\n", name);
  247.     if (lflg || sflg)
  248.         printf("total %ld\n", nkb);
  249.     formatf(dfp0, dfplast);
  250.     if (Rflg)
  251.         for (fp = dfplast - 1; fp >= dfp0; fp--) {
  252.             if (fp->ftype != 'd' ||
  253.                 !strcmp(fp->fname, ".") ||
  254.                 !strcmp(fp->fname, ".."))
  255.                 continue;
  256.             dp = (struct subdirs *)malloc(sizeof (struct subdirs));
  257.             dp->sd_name = savestr(cat(name, fp->fname));
  258.             dp->sd_next = subdirs; subdirs = dp;
  259.         }
  260.     for (fp = dfp0; fp < dfplast; fp++) {
  261.         if ((fp->fflags&ISARG) == 0 && fp->fname)
  262.             cfree(fp->fname);
  263.         if (fp->flinkto)
  264.             cfree(fp->flinkto);
  265.     }
  266.     cfree((char *)dfp0);
  267. }
  268.  
  269. getdir(dir, pfp0, pfplast)
  270.     char *dir;
  271.     struct afile **pfp0, **pfplast;
  272. {
  273.     register struct afile *fp;
  274.     PDIR *dirp;
  275.     register struct pgdirent *dp;
  276.     int nb, nent = 20;
  277.     char *res;
  278.  
  279.     /*
  280.      * This code (opendir, readdir, and the "for" loop) is arranged in
  281.      * this strange manner to handle the case where UNIX lets root open
  282.      * any directory for reading, but NFS does not let root read the
  283.      * opened directory.
  284.      */
  285.     *pfp0 = *pfplast = NULL;
  286.     res = PQexec("begin");
  287.     if ((dirp = p_opendir(dir)) == NULL) {
  288.         printf("%s unreadable\n", dir);        /* not stderr! */
  289.         return (0);
  290.     }
  291.     p_errno = 0;
  292.     if (((dp = p_readdir(dirp)) == NULL) && (p_errno != 0)) {
  293.         /* root reading across NFS can get to this error case */
  294.         printf("%s unreadable\n", dir);        /* not stderr! */
  295.         p_closedir(dirp);
  296.         return (0);
  297.     }
  298.     fp = *pfp0 = (struct afile *)calloc(nent, sizeof (struct afile));
  299.     *pfplast = *pfp0 + nent;
  300.     nb = 0;
  301.     for (; dp != NULL; dp = p_readdir(dirp)) {
  302.         if (dp->d_ino == 0)
  303.             continue;
  304.         if (aflg == 0 && dp->d_name[0]=='.' &&
  305.             (Aflg == 0 || dp->d_name[1]==0 ||
  306.             dp->d_name[1]=='.' && dp->d_name[2]==0))
  307.                 continue;
  308.         if (gstat(fp, cat(dir, dp->d_name), Fflg+Rflg, &nb) == 0)
  309.             continue;
  310.         fp->fnum = dp->d_ino;
  311.         fp->fname = savestr(dp->d_name);
  312.         fp++;
  313.         if (fp == *pfplast) {
  314.             *pfp0 = (struct afile *)realloc((char *)*pfp0,
  315.                 2 * nent * sizeof (struct afile));
  316.             if (*pfp0 == 0) {
  317.                 fprintf(stderr, "ls: out of memory\n");
  318.                 exit(1);
  319.             }
  320.             fp = *pfp0 + nent;
  321.             *pfplast = fp + nent;
  322.             nent *= 2;
  323.         }
  324.     }
  325.     p_closedir(dirp);
  326.     *pfplast = fp;
  327.     res = PQexec("end");
  328.     return (kbytes(dbtob(nb)));
  329. }
  330.  
  331. int    stat(), lstat();
  332.  
  333. struct afile *
  334. gstat(fp, file, statarg, pnb)
  335.     register struct afile *fp;
  336.     char *file;
  337.     int statarg;
  338.     int *pnb;    /* (int *)0 if file is ISARG */
  339. {
  340.     int (*statf)() = Lflg ? p_stat : lstat;
  341.     char buf[BUFSIZ]; int cc;
  342.     static struct afile azerofile;
  343.  
  344.     *fp = azerofile;
  345.     fp->fflags = 0;
  346.     fp->fnum = 0;
  347.     fp->ftype = '-';
  348.     if (statarg || sflg || lflg || tflg || cflg) {
  349.         struct pgstat stb, stb1;
  350.  
  351.         if ((*statf)(file, &stb) < 0) {
  352.             if (p_errno == ENOENT)
  353.                 fprintf(stderr, "%s not found\n", file);
  354.             else {
  355.                 if (p_errno != 0) {
  356.                     fprintf(stderr, "ls: ");
  357.                     perror(file);
  358.                 }
  359.             }
  360.             return (0);
  361.         }
  362.         fp->fblks = (stb.st_size+511)/512;
  363.         fp->fsize = stb.st_size;
  364.         switch (stb.st_mode & _S_IFMT) {
  365.             case S_IFDIR:
  366.                 fp->ftype = 'd'; break;
  367.         }
  368.         fp->fnum = 1234;
  369.         fp->fflags = stb.st_mode & ~_S_IFMT;
  370.         fp->fuid = stb.st_uid;
  371.         if (uflg)
  372.             fp->fmtime = stb.st_atime;
  373.         else if (cflg)
  374.             fp->fmtime = stb.st_ctime;
  375.         else
  376.             fp->fmtime = stb.st_mtime;
  377.     }
  378.     return (fp);
  379. }
  380.  
  381. formatf(fp0, fplast)
  382.     struct afile *fp0, *fplast;
  383. {
  384.     register struct afile *fp;
  385.     int width = 0, w, nentry = fplast - fp0;
  386.     int i, j, columns, lines;
  387.     char *cp;
  388.  
  389.     if (fp0 == fplast)
  390.         return;
  391.     if (lflg || Cflg == 0)
  392.         columns = 1;
  393.     else {
  394.         for (fp = fp0; fp < fplast; fp++) {
  395.             int len = strlen(fmtentry(fp));
  396.  
  397.             if (len > width)
  398.                 width = len;
  399.         }
  400.         if (usetabs)
  401.             width = (width + 8) &~ 7;
  402.         else
  403.             width += 2;
  404.         columns = twidth / width;
  405.         if (columns == 0)
  406.             columns = 1;
  407.     }
  408.     lines = (nentry + columns - 1) / columns;
  409.     for (i = 0; i < lines; i++) {
  410.         for (j = 0; j < columns; j++) {
  411.             fp = fp0 + j * lines + i;
  412.             cp = fmtentry(fp);
  413.             printf("%s", cp);
  414.             if (fp + lines >= fplast) {
  415.                 printf("\n");
  416.                 break;
  417.             }
  418.             w = strlen(cp);
  419.             while (w < width)
  420.                 if (usetabs) {
  421.                     w = (w + 8) &~ 7;
  422.                     putchar('\t');
  423.                 } else {
  424.                     w++;
  425.                     putchar(' ');
  426.                 }
  427.         }
  428.     }
  429. }
  430.  
  431. fcmp(f1, f2)
  432.     register struct afile *f1, *f2;
  433. {
  434.  
  435.     if (dflg == 0 && fflg == 0) {
  436.         if ((f1->fflags&ISARG) && f1->ftype == 'd') {
  437.             if ((f2->fflags&ISARG) == 0 || f2->ftype != 'd')
  438.                 return (1);
  439.         } else {
  440.             if ((f2->fflags&ISARG) && f2->ftype == 'd')
  441.                 return (-1);
  442.         }
  443.     }
  444.     if (tflg || cflg) {
  445.         if (f2->fmtime == f1->fmtime)
  446.             return (0);
  447.         if (f2->fmtime > f1->fmtime)
  448.             return (rflg);
  449.         return (-rflg);
  450.     }
  451.     return (rflg * strcmp(f1->fname, f2->fname));
  452. }
  453.  
  454. char *
  455. cat(dir, file)
  456.     char *dir, *file;
  457. {
  458.     static char dfile[BUFSIZ];
  459.  
  460.     if (strlen(dir)+1+strlen(file)+1 > BUFSIZ) {
  461.         fprintf(stderr, "ls: filename too long\n");
  462.         exit(1);
  463.     }
  464.     if (!strcmp(dir, "") || !strcmp(dir, ".")) {
  465.         (void) strcpy(dfile, file);
  466.         return (dfile);
  467.     }
  468.     (void) strcpy(dfile, dir);
  469.     if (dir[strlen(dir) - 1] != '/' && *file != '/')
  470.         (void) strcat(dfile, "/");
  471.     (void) strcat(dfile, file);
  472.     return (dfile);
  473. }
  474.  
  475. char *
  476. savestr(str)
  477.     char *str;
  478. {
  479.     char *cp = malloc(strlen(str) + 1);
  480.  
  481.     if (cp == NULL) {
  482.         fprintf(stderr, "ls: out of memory\n");
  483.         exit(1);
  484.     }
  485.     (void) strcpy(cp, str);
  486.     return (cp);
  487. }
  488.  
  489. char    *fmtinum(), *fmtsize(), *fmtlstuff(), *fmtmode();
  490.  
  491. char *
  492. fmtentry(fp)
  493.     register struct afile *fp;
  494. {
  495.     static char fmtres[BUFSIZ];
  496.     register char *cp, *dp;
  497.  
  498.     (void) sprintf(fmtres, "%s%s%s",
  499.         iflg ? fmtinum(fp) : "",
  500.         sflg ? fmtsize(fp) : "",
  501.         lflg ? fmtlstuff(fp) : "");
  502.     dp = &fmtres[strlen(fmtres)];
  503.     for (cp = fp->fname; *cp; cp++)
  504.         if (qflg && !isprint((unsigned char)*cp))
  505.             *dp++ = '?';
  506.         else
  507.             *dp++ = *cp;
  508.     /* avoid both "->" and trailing marks */
  509.     if (Fflg && ! (lflg && fp->flinkto)) {
  510.         if (fp->ftype == 'd')
  511.             *dp++ = '/';
  512.         else if (fp->ftype == 'l')
  513.             *dp++ = '@';
  514.         else if (fp->ftype == 's')
  515.             *dp++ = '=';
  516.         else if (fp->fflags & 0111)
  517.             *dp++ = '*';
  518.     }
  519.     if (lflg && fp->flinkto) {
  520.         (void) strcpy(dp, " -> "); dp += 4;
  521.         for (cp = fp->flinkto; *cp; cp++)
  522.             if (qflg && !isprint((unsigned char) *cp))
  523.                 *dp++ = '?';
  524.             else
  525.                 *dp++ = *cp;
  526.     }
  527.     *dp++ = 0;
  528.     return (fmtres);
  529. }
  530.  
  531. char *
  532. fmtinum(p)
  533.     register struct afile *p;
  534. {
  535.     static char inumbuf[8];
  536.  
  537.     (void) sprintf(inumbuf, "%6d ", p->fnum);
  538.     return (inumbuf);
  539. }
  540.  
  541. char *
  542. fmtsize(p)
  543.     register struct afile *p;
  544. {
  545.     static char sizebuf[32];
  546.  
  547.     (void) sprintf(sizebuf, "%4ld ", kbytes(dbtob(p->fblks)));
  548.     return (sizebuf);
  549. }
  550.  
  551. char *
  552. fmtlstuff(p)
  553.     register struct afile *p;
  554. {
  555.     static char lstuffbuf[256];
  556.     char gname[32], uname[32], fsize[32], ftime[32];
  557.     register char *lp = lstuffbuf;
  558.  
  559.     /* type mode uname gname fsize ftime */
  560. /* get uname */
  561.     { char *cp = getname(p->fuid);
  562.         (void) sprintf(uname, "%-9.9s", cp);
  563.     }
  564. /* get gname */
  565.     if (gflg) {
  566.         char *cp = getgroup(p->fgid);
  567.         (void) sprintf(gname, "%-9.9s", cp);
  568.     }
  569. /* get fsize */
  570.     if (p->ftype == 'b' || p->ftype == 'c')
  571.         (void) sprintf(fsize, "%3d,%4d",
  572.             major(p->fsize), minor(p->fsize));
  573.     else if (p->ftype == 's')
  574.         (void) sprintf(fsize, "%8ld", 0);
  575.     else
  576.         (void) sprintf(fsize, "%8ld", p->fsize);
  577. /* get ftime */
  578.     { char *cp = ctime(&p->fmtime);
  579.         if ((p->fmtime < sixmonthsago) || (p->fmtime > onehourfromnow))
  580.         (void) sprintf(ftime, " %-7.7s %-4.4s ", cp+4, cp+20);
  581.         else
  582.         (void) sprintf(ftime, " %-12.12s ", cp+4);
  583.     }
  584. /* splat */
  585.     *lp++ = p->ftype;
  586.     lp = fmtmode(lp, p->fflags);
  587.     (void) sprintf(lp, "%3d %s%s%s%s",
  588.         p->fnl, uname, gflg ? gname : "", fsize, ftime);
  589.     return (lstuffbuf);
  590. }
  591.  
  592. #define S_IREAD 0000400         /* read permission, owner */
  593. #define S_IWRITE 0000200        /* write permission, owner */
  594. #define S_IEXEC 0000100         /* execute/search permission, owner */
  595. #define S_ISUID 0004000         /* set user id on execution */
  596. #define S_ISGID 0002000         /* set group id on execution */
  597. #define S_ISVTX 0001000         /* save swapped text even after use */
  598.  
  599.  
  600. int    m1[] = { 1, S_IREAD>>0, 'r', '-' };
  601. int    m2[] = { 1, S_IWRITE>>0, 'w', '-' };
  602. int    m3[] = { 3, S_ISUID|(S_IEXEC>>0), 's', S_IEXEC>>0, 'x', S_ISUID, 'S',
  603.     '-' };
  604. int    m4[] = { 1, S_IREAD>>3, 'r', '-' };
  605. int    m5[] = { 1, S_IWRITE>>3, 'w', '-' };
  606. int    m6[] = { 3, S_ISGID|(S_IEXEC>>3), 's', S_IEXEC>>3, 'x', S_ISGID, 'S',
  607.     '-' };
  608. int    m7[] = { 1, S_IREAD>>6, 'r', '-' };
  609. int    m8[] = { 1, S_IWRITE>>6, 'w', '-' };
  610. int    m9[] = { 3, S_ISVTX|(S_IEXEC>>6), 't', S_IEXEC>>6, 'x', S_ISVTX, 'T',
  611.     '-'};
  612.  
  613. int    *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
  614.  
  615. char *
  616. fmtmode(lp, flags)
  617.     char *lp;
  618.     int flags;
  619. {
  620.     int **mp;
  621.  
  622.     for (mp = &m[0]; mp < &m[sizeof (m)/sizeof (m[0])]; ) {
  623.         register int *pairp = *mp++;
  624.         register int n = *pairp++;
  625.  
  626.         while (n-- > 0) {
  627.             if ((flags&*pairp) == *pairp) {
  628.                 pairp++;
  629.                 break;
  630.             } else
  631.                 pairp += 2;
  632.         }
  633.         *lp++ = *pairp;
  634.     }
  635.     return (lp);
  636. }
  637.  
  638. /* rest should be done with nameserver or database */
  639.  
  640. #include <pwd.h>
  641. #include <grp.h>
  642. #include <utmp.h>
  643.  
  644. struct    utmp utmp;
  645.  
  646. #define    NMAX    (sizeof (utmp.ut_name))
  647. #define    SCPYN(a, b)    strncpy(a, b, NMAX)
  648.  
  649.  
  650. struct cachenode {        /* this struct must be zeroed before using */
  651.     struct cachenode *lesschild;    /* subtree whose entries < val */
  652.     struct cachenode *grtrchild;    /* subtree whose entries > val */
  653.     int val;            /* the uid or gid of this entry */
  654.     int initted;            /* name has been filled in */
  655.     char name[NMAX+1];        /* the string that val maps to */
  656. } *names, *groups;
  657.  
  658. static struct cachenode *
  659. findincache(head, val)
  660.     struct cachenode **head;
  661.     register int val;
  662. {
  663.     register struct cachenode **parent = head;
  664.     register struct cachenode *c = *parent;
  665.  
  666.     while (c != NULL) {
  667.         if (val == c->val) {
  668.             /* found it */
  669.             return (c);
  670.         } else if (val < c->val) {
  671.             parent = &c->lesschild;
  672.             c = c->lesschild;
  673.         } else {
  674.             parent = &c->grtrchild;
  675.             c = c->grtrchild;
  676.         }
  677.     }
  678.  
  679.     /* not in the cache, make a new entry for it */
  680.     *parent = c = (struct cachenode *) calloc(1, sizeof (struct cachenode));
  681.     c->val = val;
  682.     return (c);
  683. }
  684.  
  685. static char *
  686. getname(uid)
  687.     int uid;
  688. {
  689.     register struct cachenode *c;
  690.     struct passwd *pw;
  691.  
  692.     c = findincache(&names, uid);
  693.     if (c->initted == 0) {
  694.         if ((pw = getpwuid(uid)) != NULL) {
  695.             SCPYN(&c->name[0], pw->pw_name);
  696.         } else {
  697.             (void) sprintf(&c->name[0], "%-8d", uid);
  698.         }
  699.         c->initted = 1;
  700.     }
  701.     return (&c->name[0]);
  702. }
  703.  
  704. static char *
  705. getgroup(gid)
  706.     int gid;
  707. {
  708.     register struct cachenode *c;
  709.     struct group *gr;
  710.  
  711.     c = findincache(&groups, gid);
  712.     if (c->initted == 0) {
  713.         if ((gr = getgrgid(gid)) != NULL) {
  714.             SCPYN(&c->name[0], gr->gr_name);
  715.         } else {
  716.             (void) sprintf(&c->name[0], "%-8d", gid);
  717.         }
  718.         c->initted = 1;
  719.     }
  720.     return (&c->name[0]);
  721. }
  722.